/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sources;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import sys.Video;
import sys.ConsoleProgress;

/**
 *
 * @author Jonas
 */
public class BlipDay9Tv implements SourceInterface {

    private final String feed = "http://day9tv.blip.tv/posts/?skin=api&pagelen=";

    private final String cacheRssFileString = System.getProperty("user.dir")
            + "/"
            + "BlipDay9Tv.cache";

    private List<Video> localVideoList;
    private List<Video> remoteVideoList;
    private Video currentVideo;
    private String localTimestamp = "";
    private String remoteTimestamp = "";
    private ConsoleProgress cp;

    public BlipDay9Tv() throws ParserConfigurationException, SAXException, IOException {

        localVideoList = new ArrayList<Video>();

        if(!this.parseFile(localVideoList, cacheRssFileString, false)) {
            this.executeUpdate(true);
        } else {
            this.executeUpdate(false);
        }

    }

    public List<Video> getVideos() {
        return this.localVideoList;
    }

    public void executeUpdate(boolean forced) {
        try {

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(this.feed);
            doc.getDocumentElement().normalize();

            //NodeList nodeLst = doc.getElementsByTagName("response");
            // Timestamp
            remoteTimestamp = ((Element)doc.getElementsByTagName("asset").item(0)).getElementsByTagName("timestamp").item(0).getTextContent();
            if(forced) {
                this.localTimestamp = "1";
            }
            System.out.println("Remote:\t" + remoteTimestamp);
            System.out.println("Local:\t" + localTimestamp);
            if(Long.parseLong(localTimestamp) < Long.parseLong(remoteTimestamp)) {
                System.out.println("Running update...");
                remoteVideoList = new ArrayList<Video>();
                parseFile(remoteVideoList, feed + "999", true);
                System.out.println("Update finished!");

                if(remoteVideoList.size() > localVideoList.size()) {
                    for(Video v : remoteVideoList) {
                        if(!localVideoList.contains(v)) {
                            localVideoList.add(remoteVideoList.indexOf(v), v);
                            System.out.print("\tNew: ");
                        } else {
                            //System.out.print("\tOld: ");
                        }
                        System.out.println(remoteVideoList.get(remoteVideoList.indexOf(v)));
                    }
                }
                System.out.println("Total of " + remoteVideoList.size() + " videos.");
            } else {
                System.out.println("No need to update... :)");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private boolean parseFile(List<Video> videoList, String url, boolean remote) {

        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = null;
            if(remote) {
                doc = db.parse(url);
            } else {
                File file = new File(url);
                if(file.exists()) {
                    doc = db.parse(file);
                } else {
                    return false;
                }
            }
            doc.getDocumentElement().normalize();
            NodeList nodeLst = doc.getElementsByTagName("asset");
            NodeList childNodes1;
            NodeList childNodes2;
            NodeList childNodes3;
            NodeList childNodes4;
            NodeList childNodes5;
            NodeList childNodes6;
            Node titleNode;
            Node timestampNode;

            cp = new ConsoleProgress(nodeLst.getLength(), 10);

            for(int i = 0; i < nodeLst.getLength(); i++) {
                currentVideo = new Video(null, null, null);
                currentVideo.setGame(this.getGame());
                currentVideo.setSource(this.getSource());
                currentVideo.setProducer(this.getProducer());
                if(nodeLst.item(i).getNodeType() == Node.ELEMENT_NODE) {
                    titleNode = ((Element)nodeLst.item(i)).getElementsByTagName("title").item(0);
                    timestampNode = ((Element)nodeLst.item(i)).getElementsByTagName("timestamp").item(0);
                    if(i == 0) {
                        if(remote) {
                            this.remoteTimestamp = timestampNode.getTextContent();
                        } else {
                            this.localTimestamp = timestampNode.getTextContent();
                        }
                    }
                    currentVideo.setTitle(this.translateVideoTitle(titleNode.getTextContent()));
                    currentVideo.setTimestampString(timestampNode.getTextContent());
                    childNodes1 = ((Element)nodeLst.item(i)).getElementsByTagName("mediaList");
                    for(int j = 0; j < childNodes1.getLength(); j++) {
                        if(childNodes1.item(j).getNodeType() == Node.ELEMENT_NODE) {
                            childNodes2 = ((Element)childNodes1.item(j)).getElementsByTagName("media");
                            for(int k = 0; k < childNodes2.getLength(); k++) {
                                if(childNodes2.item(k).getNodeType() == Node.ELEMENT_NODE) {
                                    childNodes3 = ((Element)childNodes2.item(j)).getElementsByTagName("link");
                                    currentVideo.setUrl(childNodes3.item(0).getAttributes().item(0).toString().split("\"")[1]);
                                    childNodes4 = ((Element)childNodes2.item(j)).getElementsByTagName("width");
                                    currentVideo.setWidth(Integer.parseInt(childNodes4.item(0).getTextContent()));
                                    childNodes5 = ((Element)childNodes2.item(j)).getElementsByTagName("height");
                                    currentVideo.setHeight(Integer.parseInt(childNodes5.item(0).getTextContent()));
                                    childNodes6 = ((Element)childNodes2.item(j)).getElementsByTagName("duration");
                                    currentVideo.setDuration(Integer.parseInt(childNodes6.item(0).getTextContent()));
                                }
                            }
                        }
                    }
                }
                cp.tick();
                videoList.add(currentVideo);
            }
            System.out.println("");
            if(remote) {
                writeXmlFile(doc, cacheRssFileString);
            }
            
        } catch(Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    private String translateVideoTitle(String title) {
        title = title.replaceAll(":", " -");
        if(title.contains("D9D")) {
            String returnMe = "";
            String normalize = title.replaceAll(" ", "-");
            String[] n = normalize.split("-");
            try {
                returnMe = ("Day[9] Daily #" + Integer.parseInt(n[1]) + " -");
                for(int i = 2; i < n.length; i++) {
                    returnMe += (" " + n[i]);
                }
            } catch(Exception e) {

            }
            return returnMe;
        } else if(title.contains("Day[9] Daily")) {
            //TODO normalize string
            System.out.println("TODO: Normalize - " + title);
        }
        return title;
    }

    // This method writes a DOM document to a file
    public static void writeXmlFile(Document doc, String filename) {
        try {
            // Prepare the DOM document for writing
            Source source = new DOMSource(doc);

            // Prepare the output file
            System.out.println("Writing cache to file: " + filename);
            File file = new File(filename);
            Result result = new StreamResult(file);

            // Write the DOM document to the file
            Transformer xformer = TransformerFactory.newInstance().newTransformer();
            xformer.transform(source, result);
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
    }

	@Override
	public String getSource() {
		return "Blip.tv";
	}

	@Override
	public String getGame() {
		return "Starcraft II";
	}

	@Override
	public String getProducer() {
		return "Day [9]";
	}
    
}
